//
// Created by tcj on 2022/3/7.
//

#ifndef __SYLAR_TIMER_H__
#define __SYLAR_TIMER_H__

#include "memory"
#include "thread.h"
#include "set"
#include "util.h"
#include "vector"

/*
 * 定时器执行逻辑
 *  这里的定时器采用最小堆设计，所有定时器根据绝对的超时时间点排序，每次取出离当前时间最近的一个超时时间点
 *  计算出超时需要等待的时间，然后等待超时，
 *  超时时间到后，获取当前的绝对时间点，
 *  然后把最小堆李超时时间点小于这个时间点的定时器都收集起来，执行他们的回调函数
 * */
namespace sylar{

    class TimerManager;

    class Timer : public std::enable_shared_from_this<Timer>{
    friend class TimerManager;
    public:
        typedef std::shared_ptr<Timer> ptr;
//        取消定时器
        bool cancel();
//        刷新设置定时器的执行时间
        bool refersh();
//       重置定时器时间
        bool reset(uint64_t ms,bool from_now);
    private:
//        ms:定时器执行间隔时间
//        cb：回调函数
//         recurring:是否循环
//        manager:定时器管理器
        Timer(uint64_t ms,std::function<void()> cb,
                    bool recurring,TimerManager* manager);
//        next:执行的时间戳
        Timer(uint64_t next);


    private:
        bool m_recurring = false;  //是否循环定时器
        uint64_t m_ms=0;           //执行周期
        uint64_t m_next = 0;        //精确的执行时间
        std::function<void()> m_cb;     //回调函数
        TimerManager* m_manager = nullptr; //定时器管理器
    private:
//        定时器比较仿函数 -- 比较绝对超时时间
        struct Comparator{
            bool operator()(const Timer::ptr& lhs,
                                    const Timer::ptr& rhs) const;
        };
    };

    //所有的timer对象都是由timermanager类进行管理

    /*
     * 提供创建一个定时器，获取最近的一个定时器的超时时间，
     * 以及获取全部已经超时的定时器回调函数
     *
     * */
    class TimerManager{
    friend Timer;

    public:
        typedef RWMutex RWMutexType;

        TimerManager();
        virtual ~TimerManager();

        //添加定时器
        // ms 定时器执行间隔时间，
        Timer::ptr addTimer(uint64_t ms,std::function<void()> cb
                                    ,bool recurring=false);

        //添加条件定时器
        Timer::ptr addConditionTimer(uint64_t ms,std::function<void()> cb
                                     ,std::weak_ptr<void> weak_cond
                                     ,bool recurring=false);

        uint64_t  getNextTimer();
//        获取需要执行的定时器的回调函数列表
        void listExpiredCb(std::vector<std::function<void()> >& cbs );
    protected:
//      当新的定时器插入到timer集合的首部时，timermanager通过该
//        方法来通知iomanager立刻更新当前的epoll_wait超时
        virtual void onTimerInsertedAtFront()=0;
    //将定时器添加到管理器中
        void addTimer(Timer::ptr val,RWMutexType::WriteLock lock);
        //是否有定时器
        bool hasTimer();
    private:
//        timermanager负责检查是否发生了校时
        bool detectClockRollover(uint64_t now_ms);
    private:
        RWMutexType m_mutex;
//        定时器的最小堆结构----(方便获取到当前的最小定时器)
        std::set<Timer::ptr,Timer::Comparator> m_timers;
       //是否触发onTimerInsertedAtFront
        bool m_tickled = false;
        //上次执行时间
        uint64_t m_previousTime=0;
    };
}


#endif //__SYLAR_TIMER_H__
